<!--
 * @Author: aster lipian1004@163.com
 * @Date: 2025-03-21 14:12:18
 * @FilePath: \aster-flowable-uniapp\src\pages\process\process-render.vue
 * @Description: 渲染流程
 * Copyright (c) 2025 by Aster, All Rights Reserved.
-->
<template>
  <view class="process">
    <!-- 导航栏 -->
    <aster-back
      ref="asterBackRef"
      font-color="#606266"
      :show-title="true"
      :title="_baseFormInfo.formName"
      style="background-color: #fff"
    />
    <view>
      <!-- 表单内容 -->
      <van-tabs v-model:active="activeTab" @click-tab="onClickTab">
        <van-tab title="表单详情" name="form" key="form" style="position: relative">
          <form-render
            ref="formRenderRef"
            v-model:form-data="formData"
            :form-items="_formItems"
            :form-info="_baseFormInfo"
          />
          <view class="form-complete" v-if="formStatus === '9'">
            <img src="@/assets/images/complete.png" alt="审批通过" />
          </view>
        </van-tab>
        <van-tab title="流程日志" name="log" key="log">
          <process-log ref="processLogRef" v-if="showLog" :log-list="processLogList" />
        </van-tab>
        <van-tab title="查看流程" name="process" key="process">
          <flow-render ref="processRenderRef" :data="_process" :active-node-id="activeNodeId" />
        </van-tab>
      </van-tabs>
    </view>
    <!-- 底部操作按钮 -->
    <aster-tabbar
      v-if="isNotEmpty(_buttonList)"
      :customStyle="{
        borderTopLeftRadius: '10px',
        borderTopRightRadius: '10px',
      }"
    >
      <van-tabbar v-model="activeBtn" active-color="#1989fa" inactive-color="#323233">
        <van-tabbar-item
          v-for="(item, index) in _buttonList.slice(0, 5)"
          @click="handleAction(item)"
          :key="index"
        >
          <template #icon>
            <i :class="getButtonIcon(item.name)"></i>
          </template>
          <span class="text-sm">{{ item.operation }}</span>
        </van-tabbar-item>
      </van-tabbar>
    </aster-tabbar>

    <!-- 更多按钮 -->
    <more-button
      v-if="isNotEmpty(_buttonList) && _buttonList.length > 4"
      :options="_buttonList.slice(5)"
      :showShare="showShare"
      @closeShare="closeShare"
      @onSelect="handleAction"
    />

    <!-- 审批任务 -->
    <approve-task
      v-if="isNotEmpty(taskId)"
      ref="approveTaskRef"
      :task-id="taskId"
      :form-id="formInfo.id"
      :form-data="formData"
      @cancel="handleCancelApprove"
      @confirm="handleConfirmApprove"
    />

    <form-comment ref="formCommentRef" :procInstId="procInstId" />
  </view>
</template>
<script setup lang="ts">
  import {
    getInstanceLogsApi,
    instanceInfoApi,
    instanceInfoByInstanceIdApi,
  } from '@/api/workflow/task';
  import { isEmpty, isNotEmpty } from '@/utils/is';
  import { HideLoading, Loading, Toast } from '@/utils/uniapi/prompt';
  import {
    convertDataTypes,
    evaluateFormula,
    getButtonIcon,
    setFormPermission,
  } from '@/utils/workflow';
  import { computed, reactive, ref } from 'vue';
  import FormRender from '../form/form-render.vue';
  import FormComment from '../form/form-comment.vue';
  import ProcessLog from './process-log.vue';
  import MoreButton from '@/components/approve/more-button.vue';
  import ApproveTask from '@/components/approve/approve-task.vue';
  import { onLoad } from '@dcloudio/uni-app';
  import { ProcessResultEnum } from '@/enums/workFlowEnum';
  import { useUserStore } from '@/store/modules/user';

  const userStore = useUserStore();

  // 活动页签
  const activeTab = ref<string>('form');
  // 显示footer
  const isFooter = ref<boolean>(false);
  // 表单数据
  const formData = ref<WorkForm.FormDataModel>({});
  // 表单状态
  const formStatus = ref<string>('');
  // 表单实例
  const formInstanceId = ref<string>('');
  // 流程实例id
  const procInstId = ref<string>('');
  // 按钮权限 格式: {name: "agree", operation: "同意", status: true}
  const buttonPermission = ref<WorkForm.ButtonPermission[]>([]);
  // 表单信息
  const formInfo = ref<WorkForm.FormModel>({
    icon: 'iconfont icon-gengduo',
    iconColor: '',
    labelPosition: 'left',
    formName: '未命名表单',
    formItems: [],
    process: {},
    labelWidth: 80,
    listSettings: {
      queryItems: [],
      columns: [],
      sortBy: 'create_time',
      sortDirection: 'desc',
      actions: [],
    },
  });
  // 表单权限
  const formPermission = ref<Process.FormPermissionModel>({});
  // 注册组件
  const formRenderRef = ref();
  const asterBackRef = ref();
  const approveTaskRef = ref();
  const processLogRef = ref();
  const formCommentRef = ref();
  // 任务ID
  const taskId = ref('');
  // 查询参数
  const queryParams = reactive<Process.InstanceQueryParams>({
    id: '',
    code: '',
    procDefId: '',
  });
  // 显示日志
  const showLog = ref<boolean>(false);
  // 当前流程节点ID
  const activeNodeId = ref<string[]>([]);
  // 流程日志
  const processLogList = ref<WorkForm.ProcessResult>({
    instanceLogs: [],
    approveResult: '',
    approveResultText: '',
  });
  // 选中的按钮
  const activeBtn = ref('');
  // 是否显示更多按钮
  const showShare = ref(false);

  /**
   * @description: 点击tab页签
   * @param {*} name 值
   * @return {*}
   */
  const onClickTab = ({ name }) => {
    if (name === 'log') {
      getInstanceLogs();
    }
  };

  /**
   * @description: 获取流程日志
   * @param {*} procInstId 流程实例ID
   * @return {*}
   */
  const getInstanceLogs = async () => {
    Loading('');
    showLog.value = false;
    processLogList.value = { instanceLogs: [], approveResult: '', approveResultText: '' };
    await getInstanceLogsApi(procInstId.value).then((res) => {
      HideLoading();
      showLog.value = true;
      processLogList.value = res.data;
      // 如果是正在进行中
      if (processLogList.value.approveResult == ProcessResultEnum.PROCESSING) {
        let instanceLogs = processLogList.value.instanceLogs;
        console.info(instanceLogs[instanceLogs.length - 1][0]);
        activeNodeId.value = [instanceLogs[instanceLogs.length - 1][0].nodeId];
      }
    });
  };

  /**
   * @description: 提交校验
   * @return {*}
   */
  const submitValidate = () => {
    if (formInfo.value.settings && formInfo.value.settings.submitValidates) {
      const validates = formInfo.value.settings.submitValidates;
      for (let i = 0; i < validates.length; i++) {
        const v = validates[i];
        if (v.enable) {
          const r = evaluateFormula(v.formula, formData.value);
          if (r) {
            Toast(v.errorMessage);
            return false;
          }
        }
      }
    }
    return true;
  };

  /**
   * @description: 验证表单
   * @return {*}
   */
  const validateForm = async (callback: Function) => {
    // 表单校验
    await formRenderRef.value.validate(() => {
      // 提交校验
      if (submitValidate()) {
        callback();
      }
    });
  };

  /**
   * @description: 关闭更多按钮
   * @return {*}
   */
  const closeShare = () => {
    showShare.value = false;
    activeBtn.value = '';
  };

  /**
   * @description: 处理按钮事件
   * @param item
   */
  const handleAction = (item: WorkForm.ButtonPermission) => {
    console.log('handleAction--->', item);
    if (item.name === 'more') {
      showShare.value = true;
    } else if (item.name === 'comment') {
      activeBtn.value = '';
      formCommentRef.value.init(true);
    } else if (item.name === 'edit') {
      console.log('编辑');
    } else {
      validateForm(() => {
        approveTaskRef.value.init(item);
      });
    }
  };

  /**
   * @description: 关闭审批
   * @return {*}
   */
  const handleCancelApprove = () => {
    activeBtn.value = '';
  };

  /**
   * @description: 提交审批
   * @return {*}
   */
  const handleConfirmApprove = () => {
    // 延迟400ms后刷新列表，防止流程状态还没更改过来查询到的数据还是旧的数据
    setTimeout(() => {
      // 提交成功，刷新
      asterBackRef.value.toback();
    }, 400);
    ``;
  };

  /**
   * @description: 获取表单信息
   * @param {string} id 表单实例表的ID, 非proc_inst_id
   * @param {string} code 表单编码
   * @param {string} procDefId 流程定义ID
   * @return {*}
   */
  const getInstanceInfo = async (id: string, code: string, procDefId: string) => {
    if (isEmpty(id) || isEmpty(code)) {
      Toast('参数有问题,请检查传参!');
      return;
    }
    // 查询参数
    queryParams.id = id;
    queryParams.code = code;
    queryParams.procDefId = procDefId;
    await instanceInfoApi(queryParams).then(({ data }) => {
      // 表单信息
      const formDesignInfo = data.formInfo;
      if (isNotEmpty(formDesignInfo)) {
        formInfo.value = formDesignInfo;
      }
      // 表单权限
      if (data.formPermission) {
        formPermission.value = data.formPermission;
      }
      // 表单数据
      const instanceInfo = data.instanceInfo;
      // 任务ID
      taskId.value = instanceInfo['taskId'];
      // 流程实例id
      procInstId.value = instanceInfo['proc_inst_id'];
      if (isNotEmpty(instanceInfo)) {
        formStatus.value = instanceInfo['form_status'];
        for (const key in instanceInfo) {
          if (key.indexOf('field') != -1) {
            formData.value[key] = convertDataTypes(
              formInfo.value.formItems,
              key,
              instanceInfo[key],
            );
          } else {
            formData.value[key] = instanceInfo[key];
          }
        }
      }
      // 当前节点配置信息，包括按钮、表单权限
      const nodeConfigInfo = data.nodeConfig;
      // 获取按钮权限列表
      if (isNotEmpty(nodeConfigInfo)) {
        buttonPermission.value = nodeConfigInfo?.buttonPermission || [];
      } else {
        buttonPermission.value = [];
      }
    });
  };

  /**
   * @description: 通过实例id获取表单信息
   * @param {string} code 表单编码
   * @param {string} procInstId 流程实例id
   * @return {*}
   */
  const getInstanceInfoByInstanceId = async (code: string, instanceId: string) => {
    if (isEmpty(instanceId) || isEmpty(code)) {
      Toast('参数有问题,请检查传参!');
      return;
    }
    procInstId.value = instanceId;
    await instanceInfoByInstanceIdApi(code, instanceId).then(({ data }) => {
      // 表单信息
      const formDesignInfo = data.formInfo;
      if (isNotEmpty(formDesignInfo)) {
        formInfo.value = formDesignInfo;
      }
      // 表单权限
      if (data.formPermission) {
        formPermission.value = data.formPermission;
      }
      // 表单数据
      const instanceInfo = data.instanceInfo;
      taskId.value = instanceInfo['taskId'];
      if (isNotEmpty(instanceInfo)) {
        formStatus.value = instanceInfo['form_status'];
        for (const key in instanceInfo) {
          if (key.indexOf('field') != -1) {
            formData.value[key] = convertDataTypes(
              formInfo.value.formItems,
              key,
              instanceInfo[key],
            );
          }
        }
      }
      // 当前节点配置信息，包括按钮、表单权限
      const nodeConfigInfo = data.nodeConfig;
      // 获取按钮权限列表
      if (isNotEmpty(nodeConfigInfo)) {
        buttonPermission.value = nodeConfigInfo?.buttonPermission || [];
      } else {
        buttonPermission.value = [];
      }
      // 默认不显示footer
      isFooter.value = false;
    });
  };

  /**
   * @description: 按钮列表
   * @return {*}
   */
  const _buttonList = computed(() => {
    const commentBtn = {
      name: 'comment',
      operation: '评论',
      status: true,
    };

    if (!buttonPermission.value) {
      return [commentBtn];
    }

    let buttonList = buttonPermission.value.filter((item) => item.status);
    if (buttonList.length > 3) {
      // 第四个按钮替换为评论
      buttonList.splice(3, 0, commentBtn);

      const moreBtn = {
        name: 'more',
        operation: '更多',
        status: true,
      };
      // 第五个按钮替换为更多
      buttonList.splice(4, 0, moreBtn);
    } else {
      buttonList.push(commentBtn);
    }
    // 超管添加编辑按钮
    // if (_superAdmin.value) {
    //   buttonList.push({
    //     name: 'edit',
    //     operation: '编辑',
    //     status: true,
    //   });
    // }
    return buttonList;
  });

  // 表单基本信息
  const _baseFormInfo = computed(() => {
    const info: WorkForm.BaseInfo = {
      formName: formInfo.value.formName,
      icon: formInfo.value.icon,
      iconColor: formInfo.value.iconColor,
      labelPosition: formInfo.value.labelPosition,
      labelWidth: formInfo.value.labelWidth,
    };
    return info;
  });

  // 表单项
  const _formItems = computed(() => {
    const formItems = JSON.parse(JSON.stringify(formInfo.value.formItems));
    // 超管拥有修改表单数据的权限
    if (isFooter.value) {
      setFormPermission(formItems, {}, 'root');
    } else {
      if (formPermission.value) {
        setFormPermission(formItems, formPermission.value, 'other');
      }
    }
    return formItems;
  });

  /**
   * @description 流程设计
   */
  const _process = computed(() => {
    return JSON.parse(JSON.stringify(formInfo.value.process));
  });

  /**
   * @description 超管权限
   */
  const _superAdmin = computed(() => {
    return userStore.isSuperAdmin();
  });

  onLoad((options) => {
    console.log(options);
    if (options && options.code && options.instanceId) {
      getInstanceInfoByInstanceId(options.code, options.instanceId);
    }
    if (options && options.id && options.code && options.procDefId) {
      getInstanceInfo(options.id, options.code, options.procDefId);
    }
  });

  defineExpose({
    getInstanceInfo,
    getInstanceInfoByInstanceId,
  });
</script>
<style scoped lang="scss">
  .form-complete {
    position: absolute;
    top: 50px;
    right: 10px;
    z-index: 10;
    pointer-events: none;
    img {
      opacity: 0.6;
    }
  }
</style>
